package com.sardine.base.hbase.persister;

import com.sardine.base.hbase.annotation.ColumnFamily;
import com.sardine.base.hbase.annotation.ColumnQualifier;
import com.sardine.base.hbase.annotation.HTableName;
import com.sardine.base.hbase.annotation.RowKey;
import com.sardine.base.hbase.exception.HException;
import com.sardine.base.reflection.ReflectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 上海京东到家元信信息技术有限公司<br>
 * Created with IntelliJ IDEA.
 * Date:2017/11/23
 * Time:10:50
 * Hbase entity 的骨架信息解析器
 *
 * @author daifeng<br>
 *         daifeng@imdada.cn
 * @since JDK 1.7 <br>
 * Copyright (c) 2017 imdada System Incorporated All Rights Reserved.
 */
public class HEntitySkeletonResolver {
    private static final Logger logger = LoggerFactory.getLogger(HEntitySkeletonResolver.class);
    /**
     * hbase 的骨架映射器
     */
    private Map<Class<?>, HEntitySkeleton> hEntitySkeletonMap = new ConcurrentHashMap();

    public HEntitySkeleton getSkeleton(Class<?> aClass) {
        HEntitySkeleton hEntitySkeleton = hEntitySkeletonMap.get(aClass);
        if (hEntitySkeleton == null) {
            synchronized (aClass) {
                hEntitySkeleton =hEntitySkeletonMap.get(aClass);
                if(hEntitySkeleton == null){
                    hEntitySkeleton = resolver(aClass);
                    hEntitySkeletonMap.put(aClass, hEntitySkeleton);
                }
            }
        }
        return hEntitySkeleton;
    }

    /**
     * 得到类上的annotation
     *
     * @param aClass
     * @return
     */
    private HTableName handlerTableName(Class<?> aClass) {
        //如果定义了ColumnFamily
        if (aClass.isAnnotationPresent(HTableName.class)) {
            HTableName annotation = aClass.getAnnotation(HTableName.class);
            return annotation;
        }
        throw new HException("@TableName annotation deficiency,class:" + aClass.getName());
    }

    /**
     * 解析 class 得到骨架
     *
     * @param aClass
     * @return
     */
    private HEntitySkeleton resolver(Class<?> aClass) {
        HTableName HTableNameAnnotation = handlerTableName(aClass);
        String tableName = HTableNameAnnotation.value();
        String columnFamily = HTableNameAnnotation.columnFamily();
        HEntitySkeleton entitySkeleton = new HEntitySkeleton();
        entitySkeleton.setClassName(aClass);
        entitySkeleton.setTableName(tableName);
        //属性值
        List<HEntitySkeleton.FiledDesc> filedDescList = entitySkeleton.getFiledDescList();
        List<Field> fields = ReflectionUtils.getAllFields(aClass);
        boolean containsRowKey = false;
        for (Field field : fields) {
            HEntitySkeleton.FiledDesc filedDesc = new HEntitySkeleton.FiledDesc();
            //设置映射属性
            filedDesc.setFiled(field);
            //得到类型
            String typeName = field.getType().getName();
            //设置属性的类型
            filedDesc.setType(typeName);
            //得到属性名称
            String fieldName = field.getName();
            //设置属性名称
            filedDesc.setFieldName(fieldName);
            //如果定义了ColumnFamily
            if (field.isAnnotationPresent(ColumnFamily.class)) {
                ColumnFamily annotation = field.getAnnotation(ColumnFamily.class);
                filedDesc.setColumnFamily(annotation.name());
            } else {
                filedDesc.setColumnFamily(columnFamily);
            }
            //如果定义了ColumnQualifier
            if (field.isAnnotationPresent(ColumnQualifier.class)) {
                ColumnQualifier annotation = field.getAnnotation(ColumnQualifier.class);
                filedDesc.setQualifier(annotation.name());
            } else {
                filedDesc.setQualifier(fieldName);
            }
            //如果定义了rowKey
            if (field.isAnnotationPresent(RowKey.class)) {
                if (!containsRowKey) {
                    RowKey annotation = field.getAnnotation(RowKey.class);
                    entitySkeleton.setGeneratorEnum(annotation.generator());
                    //设置rowKey
                    entitySkeleton.setRowKey(filedDesc);
                    containsRowKey = true;
                } else {
                    throw new HException("annotation 重复，" + aClass.getName() + "存在多个@RowKey");
                }
            }
            //保存属性描述
            filedDescList.add(filedDesc);
        }

        if (!containsRowKey) {
            throw new HException("@RowKey annotation deficiency,class:" + aClass.getName());
        }
        return entitySkeleton;
    }
}
